home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
wasm223.zip
/
SERIAL1.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-05-04
|
15KB
|
494 lines
;**********************************;
; WASM Serial I/O, Basic Routines ;
; By Eric Tauck ;
; ;
; Defines: ;
; ;
; ComBuf assign local buffer ;
; ComAll allocate buffer ;
; ComRel release buffer ;
; ComOpn open serial port ;
; ComClo close serial port ;
; ComClr clear buffer ;
; ComByt return bytes in buffer ;
; ComGet input a byte ;
; ComPut output a byte ;
; ;
; Requires: ;
; ;
; MEMORY.ASM ;
;**********************************;
jmp _serial1_end
PARITY_NONE EQU 0 ;no parity
PARITY_ODD EQU 1 ;odd parity
PARITY_EVEN EQU 2 ;even parity
;--- serial port interrupt data
_COM_PIC01 EQU 21H ;8259 programable interrupt controller
_COM_PIC00 EQU 20H ;" " " "
_COM_EOI EQU 20H ;end of interrupt command
;--- line status register values
_COM_XMITREADY EQU 20h
;--- modem control register values
_COM_DTR EQU 1
_COM_RTS EQU 2
_COM_OUT2 EQU 8
;--- interrupt enable register signals
_COM_DATAREADY EQU 1
;--- modem initialization bits
_COM_DIVLATCH EQU 80H ;divlatch bit value
_COM_PARSHIFT EQU 3 ;parity bit shift
_COM_STOPSHIFT EQU 2 ;stop bit shift
_COM_WORDSHIFT EQU 0 ;word bit shift
;--- commmunications record offsets
_COM_PORT EQU 0 ;port number
_COM_BUFBEG EQU 1 ;buffer begin address
_COM_BUFEND EQU 5 ;buffer end offset
_COM_BUFPTR1 EQU 7 ;current buffer write address
_COM_BUFPTR2 EQU 11 ;current buffer read address
_COM_BUFSIZE EQU 15 ;input buffer size
_COM_BUFBYTE EQU 17 ;bytes in buffer
_COM_INTOLD EQU 19 ;old interrupt vector
_COM_INTNUM EQU 23 ;interrupt number
_COM_INTMSK EQU 24 ;interrupt enable/disable mask
_COM_TXDATA EQU 25 ;transmit data
_COM_RXDATA EQU 27 ;receive data
_COM_DIVLSB EQU 29 ;baud rate divisor lsb
_COM_DIVMSB EQU 31 ;baud rate divisor msb
_COM_INTENABLE EQU 33 ;interrupt enable
_COM_INTIDENT EQU 35 ;interrupt identification
_COM_LINECTL EQU 37 ;line control
_COM_MODEMCTL EQU 39 ;modem control
_COM_LINESTAT EQU 41 ;line status
_COM_MODEMSTAT EQU 43 ;modem status
SERIAL_RECORD EQU 45 ;bytes in serial port record
;--- interrupt data pointers
_com_data0B LABEL DWORD
DW ?, ?
_com_data0C LABEL DWORD
DW ?, ?
;========================================
; Communications interrupt handlers.
_Com_Int0B LABEL NEAR ;entry point for interrupt 11
push bx
push ds
seg cs
lds bx, _Com_Data0B
jmps _cmint1
_Com_Int0C LABEL NEAR ;entry point for interrupt 12
push bx
push ds
seg cs
lds bx, _Com_Data0C
_cmint1 push ax
push dx
push di
push es
mov al, _COM_EOI ;end of interrupt
out _COM_PIC00, al ;send to controller
;--- get byte
mov dx, [bx + _COM_RXDATA] ;input port
in al, dx ;get byte
;--- store byte
les di, [bx + _COM_BUFPTR1] ;buffer write address
cmp di, [bx + _COM_BUFEND] ;check if at end
jne _cmint2
mov di, [bx + _COM_BUFBEG] ;wrap to start
_cmint2 seg es
mov [di], al ;save byte
inc di ;increment pointer
mov [bx + _COM_BUFPTR1], di ;save pointer
;--- update bytes in buffer
mov ax, [bx + _COM_BUFBYTE] ;load byte count
cmp ax, [bx + _COM_BUFSIZE] ;compare to size
je _cmint3 ;skip increment if full
inc WORD [bx+_COM_BUFBYTE] ;increment bytes
;--- finished
_cmint3 pop es
pop di
pop dx
pop ax
pop ds
pop bx
iret
;========================================
; Assign a local communications buffer.
;
; In: BX= record address; AX= buffer
; address; CX= size of buffer.
ComBuf PROC NEAR
mov [bx + _COM_BUFBEG + 2], cs ;segment
mov [bx + _COM_BUFBEG], ax ;buffer base
mov [bx + _COM_BUFSIZE], cx ;buffer size
add ax, cx
mov [bx + _COM_BUFEND], ax ;end of buffer
ret
ENDP
;========================================
; Allocate a communications buffer.
;
; In: BX= record address; AX= size of
; buffer.
;
; Out: CY= set if error; AL= error code
; if error; DX= memory available (if
; out of memory).
ComAll PROC NEAR
push bx
call MemAll ;allocate memory
pop bx
jc _cmall1
mov [bx + _COM_BUFBEG + 2], ax ;buffer segment
mov WORD [bx + _COM_BUFBEG], 0 ;buffer base
mov [bx + _COM_BUFSIZE], dx ;buffer size
mov [bx + _COM_BUFEND], dx ;end of buffer
_cmall1 ret
ret
ENDP
;========================================
; Release a communications buffer.
;
; In: BX= record address.
ComRel PROC NEAR
mov ax, [bx + _COM_BUFBEG + 2] ;load segment
mov dx, cs ;current segment
cmp ax, dx ;check if local buffer
je comrel1
call MemRel ;release memory
comrel1 ret
ENDP
;========================================
; Open communications port.
;
; In: BX= record address; AL= port (1 or
; 2); AH= parity; DX= baud; CL= data
; bits; CH= stop bits.
ComOpn PROC NEAR
push di
mov di, bx
push dx
push ax
;--- get intialization byte
mov dx, cx
mov al, _COM_DIVLATCH
mov cl, _COM_PARSHIFT
shl ah, cl
or al, ah
mov cl, _COM_WORDSHIFT
sub dl, 5
shl dl, cl
or al, dl
mov cl, _COM_STOPSHIFT
dec dh
shl dh, cl
or al, dh
pop dx ;restore port number
push ax ;save initialization byte for later
;--- close first if open and clear buffer
push dx
mov bx, di
call ComClr ;clear buffer
pop ax
;--- set port addresses
mov [di+_COM_PORT], al ;save port number
mov dl, al
sub dh, dh
mov ax, 003F8h ;base address
dec dx ;0 or 1
mov cl, 8
shl dx, cl
sub ax, dx ;base port address
mov [di + _COM_TXDATA], ax
mov [di + _COM_RXDATA], ax
mov [di + _COM_DIVLSB], ax
inc ax
mov [di + _COM_DIVMSB], ax
mov [di + _COM_INTENABLE], ax
inc ax
mov [di + _COM_INTIDENT], ax
inc ax
mov [di + _COM_LINECTL], ax
inc ax
mov [di + _COM_MODEMCTL], ax
inc ax
mov [di + _COM_LINESTAT], ax
inc ax
mov [di + _COM_MODEMSTAT], ax
;--- initialize port
mov dx, [di + _COM_LINECTL] ;line control port
pop bx ;restore intialization byte
mov al, bl
out dx, al ;send byte
mov dx, 00001h
mov ax, 0C200h ;baud constant
pop cx ;restore baud
div cx ;divide
mov dx, [di + _COM_DIVLSB] ;low divisor port
out dx, al ;send low byte
mov dx, [di + _COM_DIVMSB] ;high divisor port
mov al, ah
out dx, al ;send high byte
mov dx, [di + _COM_LINECTL] ;line control port
mov al, bl
xor al, _COM_DIVLATCH ;clear flag
out dx, al ;send init byte again
;--- get interrupt vector
mov al, 12 ;base interrupt
sub al, [di + _COM_PORT] ;subtract port number
inc al
mov [di + _COM_INTNUM], al ;save it
;--- save current old handler address
push es
mov ah, 35H ;get vector function
mov al, [di+_COM_INTNUM] ;vector to get
int 21H ;execute
mov [di+_COM_INTOLD], bx ;save offset
mov [di+_COM_INTOLD+2], es ;save segment
pop es
;--- hook new interrupt
mov dx, OFFSET _Com_Int0C ;interrupt 12
mov bx, OFFSET _com_data0C ;data address variable
cmp BYTE [di+_COM_INTNUM],12 ;check if 12
je _cmopn1
mov dx, OFFSET _Com_Int0B ;interrupt 11
mov bx, OFFSET _com_data0B ;data address variable
_cmopn1 mov [bx], di ;
push ds ;-- save data address
pop WORD [bx + 2] ;
mov ah, 25H ;set vector function
mov al, [di + _COM_INTNUM] ;vector to set
int 21H ;execute
;--- activate modem
mov dx, [di + _COM_MODEMCTL] ;modem control port
in al, dx ;get byte
or al, _COM_DTR OR _COM_RTS OR _COM_OUT2 ;set bits
out dx, al ;send byte
;--- enable interrupt
mov cl, 4 ;base IRQ
sub cl, [di + _COM_PORT]
inc cl
mov al, 1
shl al, cl ;interrupt mask bit
mov [di + _COM_INTMSK], al ;save it
mov ah, al
mov dx, _COM_PIC01 ;interrupt enable port
in al, dx ;get byte
not ah
and al, ah ;clear disable bit
out dx, al ;send byte
mov dx, [di+_COM_INTENABLE] ;modem interrupt enable port
mov al, _COM_DATAREADY ;data ready
out dx, al ;send byte
mov al, _COM_EOI ;end of interrupt
out _COM_PIC00, al ;send to controller
;--- flush interrupts
mov dx, [di + _COM_RXDATA]
in al, dx
mov dx, [di + _COM_INTIDENT]
in al, dx
mov dx, [di + _COM_LINESTAT]
in al, dx
mov dx, [di + _COM_MODEMSTAT]
in al, dx
pop di
ret
ENDP
;========================================
; Close communications port.
;
; In: BX= record address.
ComClo PROC NEAR
;--- clear modem control bits
mov dx, [bx + _COM_MODEMCTL] ;modem control port
in al, dx ;get byte
and al, NOT (_COM_DTR OR _COM_RTS OR _COM_OUT2) ;clear bits
out dx, al ;send byte
;--- disable interrupt
mov dx, _COM_PIC01 ;interrupt enable port
in al, dx ;get byte
or al, [bx + _COM_INTMSK] ;set disable bit
out dx, al ;send byte
;--- unhook interrupt
push ds
mov ah, 25H ;set vector function
mov al, [bx + _COM_INTNUM] ;vector to set
lds dx, [bx + _COM_INTOLD] ;old interrupt address
int 21H ;execute
pop ds
ret
ENDP
;========================================
; Clear input buffer.
;
; In: BX= record address.
ComClr PROC NEAR
cli
mov ax, [bx + _COM_BUFBEG] ;offset
mov [bx + _COM_BUFPTR1], ax
mov [bx + _COM_BUFPTR2], ax
mov ax, [bx + _COM_BUFBEG + 2] ;segment
mov [bx + _COM_BUFPTR1 + 2], ax
mov [bx + _COM_BUFPTR2 + 2], ax
mov WORD [bx + _COM_BUFBYTE], 0 ;zero bytes in buffer
sti
ret
ENDP
;========================================
; Return bytes in receive buffer.
;
; In: BX= record address.
;
; Out: AX= byte count.
ComByt PROC NEAR
mov ax, [bx + _COM_BUFBYTE] ;return bytes
ret
ENDP
;========================================
; Input a byte.
;
; In: BX= record address.
;
; Out: AL= byte received; CY= set if
; unavailable.
ComGet PROC NEAR
cmp WORD [bx + _COM_BUFBYTE], 0 ;check if any bytes in buffer
jz _cmget2 ;jump if not
push si
push es
les si, [bx + _COM_BUFPTR2] ;buffer read address
cmp si, [bx + _COM_BUFEND] ;check if at end
jne _cmget1
mov si, [bx + _COM_BUFBEG] ;wrap to start
_cmget1 seg es
mov al, [si] ;load byte
inc si
mov [bx + _COM_BUFPTR2], si ;save address
dec WORD [bx+_COM_BUFBYTE] ;increment bytes
pop es
pop si
clc
ret
;--- no byte available
_cmget2 stc
ret
ENDP
;========================================
; Output a byte. Will wait indefinitely
; for trasmit ready.
;
; In: AL= byte to send; BX= record
; address.
ComPut PROC NEAR
mov cx, ax ;save byte in CX
;--- wait for transmit ready
_cmput1 mov dx, [bx+_COM_LINESTAT] ;line status port
in al, dx ;get byte
test al, _COM_XMITREADY ;check if ready to transmit
jz _cmput1 ;loop back if not
;--- send byte
mov dx, [bx + _COM_TXDATA] ;transmit data port
mov al, cl ;byte
out dx, al ;send byte
ret
ENDP
_serial1_end